﻿using QRCoder;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Odbc;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace QrCodeDemo
{
    public partial class Form1 : Form
    {
        // 参考地址:
        // https://blog.csdn.net/qq_51793512/article/details/129599613
        // https://blog.csdn.net/qq_42047805/article/details/128417395
        // https://blog.csdn.net/qq_43562262/article/details/121675383
        // https://blog.51cto.com/u_15060515/4543481

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 获取二维码
        /// </summary>
        /// <param name="qrcode"></param>
        /// <returns></returns>
        public Bitmap GetQRCodeImage(string qrcode)
        {
            QRCodeGenerator generator = new QRCodeGenerator();
            // QR容错级别
            //概念：QR容错级别是指QR码被遮挡或残破时依然能被识别的几率，容错级别越高抗残破或遮挡的能力就越强，同时注意，提高容错级别会增大点阵密度，识别速度随之降低。
            // 以google的zxing库为例，zxing中QR码的容错率分为四个等级：
            // L（低）：容错率为7 % M（中）：容错率为15 % Q（较高）：容错率为25 % H（高）：容错率为30 %
            // 解释：假如在生成二维码时设定他的容错率为L，意味着生成的二维码最多有7 % 残破或遮挡以后仍可识别，但超过7 % 就无法识别了。即在容错率越高的情况下，二维码被残破后被成功识别出来的几率越大。
            QRCodeData data = generator.CreateQrCode(qrcode, QRCodeGenerator.ECCLevel.Q);
            QRCode code = new QRCode(data);
            Bitmap icon = new Bitmap(@"logo.png"); // 水印图片,按需设置
            /* GetGraphic方法参数说明
            public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon = null, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true)
            * 
                int pixelsPerModule:生成二维码图片的像素大小 
            * 
                Color 二维码前景色   一般设置为Color.Black 黑色
            * 
                Color 二维码背景色   一般设置为Color.White 白色
            * 
                Bitmap icon :二维码 水印图标 例如：Bitmap icon = new Bitmap(context.Server.MapPath("~/images/zs.png")); 默认为NULL ，加上这个二维码中间会显示一个图标
            * 
                int iconSizePercent： 水印图标的大小比例
            * 
                int iconBorderWidth： 水印图标的边框
            * 
                bool drawQuietZones:静止区，位于二维码某一边的空白边界,用来阻止读者获取与正在浏览的二维码无关的信息 即是否绘画二维码的空白边框区域 默认为true
           */
            Bitmap qrImage = code.GetGraphic(10, Color.Black, Color.White, icon, 15, 6, true);
            //Bitmap qrImage = code.GetGraphic(5);
            qrImage = InsertWords(qrImage, qrcode);
            return qrImage;
        }

        /// <summary>
        /// 绑定到pictureBox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            pictureBox1.Image = GetQRCodeImage(textBox1.Text.Trim());
            // 设置背景平铺
            pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        }

        /// <summary>
        /// 二维码下面加上文字
        /// </summary>
        /// <param name="qrImg">QR图片</param>
        /// <param name="content">文字内容</param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static Bitmap InsertWords(Bitmap qrImg, string content)
        {
            Bitmap backgroudImg = new Bitmap(qrImg.Width, qrImg.Height);
            backgroudImg.MakeTransparent();
            Graphics g2 = Graphics.FromImage(backgroudImg);
            g2.Clear(Color.Transparent);
            //画二维码到新的面板上
            g2.DrawImage(qrImg, 0, 0);

            if (!string.IsNullOrEmpty(content))
            {
                FontFamily fontFamily = new FontFamily("楷体");
                Font font1 = new Font(fontFamily, 20f, FontStyle.Bold, GraphicsUnit.Pixel);

                //文字长度 
                int strWidth = (int)g2.MeasureString(content, font1).Width;
                //总长度减去文字长度的一半  （居中显示）
                int wordStartX = (qrImg.Width - strWidth) / 2;
                int wordStartY = qrImg.Height - 25;

                g2.DrawString(content, font1, Brushes.Black, wordStartX, wordStartY);
            }

            g2.Dispose();

            return backgroudImg;
        }

        /// <summary>
        /// 生成二维码并保存到本地
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            CreateQRCode(this.textBox1.Text, String.Empty);
        }

        /// <summary>
        /// 创建二维码
        /// </summary>
        /// <param name="text"></param>
        /// <param name="filepath"></param>
        public void CreateQRCode(string text, string filepath)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                MessageBox.Show("请输入要生成的二维码文本!");
                return;
            }

            QRCodeGenerator qrGenerator = new QRCodeGenerator();
            QRCodeData qrCodeData = qrGenerator.CreateQrCode(text, QRCodeGenerator.ECCLevel.Q);
            QRCode qrcode = new QRCode(qrCodeData);

            var res = !string.IsNullOrWhiteSpace(filepath) ? new Bitmap(filepath) : null;
            Bitmap qrCodeImage = qrcode.GetGraphic(10, Color.Black, Color.White, res, 15, 6, true);
            string path = $"{Directory.GetCurrentDirectory()}/Images/{DateTime.Now.ToString("yyyy-MM-dd")}";
            if (!Directory.Exists(path))
            {
                // 不存在在则创建文件夹
                Directory.CreateDirectory(path);
            }

            // 定义文件名(:ffff:万分之一秒)
            string fileName = path + $"/{DateTime.Now:ffff}qrcode.png";

            // 保存
            qrCodeImage.Save(fileName);
            // 设置pictureBox的图片为我们的二维码图片
            this.pictureBox1.Image = Image.FromFile(fileName);
            // 设置背景图平铺
            this.pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
            this.pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        }

        /// <summary>
        /// 上传logo并生成二维码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            // 设置打开对话框初始化目录
            ofd.InitialDirectory = Application.StartupPath;
            // 对话框的标题
            ofd.Title = "请选择要打开的文件";
            // 只能选择一个文件
            ofd.Multiselect = true;
            // 筛选的文件格式
            ofd.Filter = "图片文件|*.jpg|所有文件|*.*";
            // 设置文件对话框当前选定筛选器的索引
            ofd.FilterIndex = 2;
            // 设置对话框是否记忆之前打开的目录
            ofd.RestoreDirectory = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                // 获取带文件路径的文件名
                string filepath = ofd.FileName;
                // 调用公共方法
                this.CreateQRCode(this.textBox1.Text, filepath);
            }
        }

        /// <summary>
        /// 窗体加载删除二维码图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            string path = $"{Directory.GetCurrentDirectory()}/Images";

            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
            }
        }
    }
}
